package com.xiran.srpingboottemplateself.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.xiran.srpingboottemplateself.filter.JwtAuthenticationFilter;
import com.xiran.srpingboottemplateself.filter.JwtLoginProcessingFilter;
import com.xiran.srpingboottemplateself.handler.RestAuthenticationEntryPoint;
import com.xiran.srpingboottemplateself.handler.RestAuthenticationFailureHandler;
import com.xiran.srpingboottemplateself.handler.RestAuthenticationSuccessHandler;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import java.util.Arrays;

@Configuration
@RequiredArgsConstructor
public class WebSecurityConfig {

    private final JwtAuthenticationFilter jwtAuthenticationFilter;
    private final RestAuthenticationEntryPoint authenticationEntryPoint;
    // 注入ObjectMapper（用于解析JSON请求体）
    private final ObjectMapper objectMapper;

    @Autowired
    private final RestAuthenticationSuccessHandler authenticationSuccessHandler;

    @Autowired
    private final RestAuthenticationFailureHandler authenticationFailureHandler;

    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception {
        return config.getAuthenticationManager();
    }

    // 【新增】配置JwtLoginProcessingFilter并注入AuthenticationManager
    @Bean
    public JwtLoginProcessingFilter jwtLoginProcessingFilter(AuthenticationManager authenticationManager) {
        JwtLoginProcessingFilter filter = new JwtLoginProcessingFilter(objectMapper);
        // 关键：设置AuthenticationManager
        filter.setAuthenticationManager(authenticationManager);
        // 正确写法：使用注入的实例对象（变量名）
        filter.setAuthenticationSuccessHandler(authenticationSuccessHandler); // 注意是小写开头的变量名
        filter.setAuthenticationFailureHandler(authenticationFailureHandler); // 注意是小写开头的变量名
        return filter;
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                // 禁用 CSRF 和 CORS 配置
                .csrf().disable()
                .cors().configurationSource(corsConfigurationSource()).and()

                // 认证授权配置
                .authorizeHttpRequests(authz -> authz
                        // 公开端点 - 确保登录接口允许匿名访问
                        .antMatchers("/login", "/api/user/login","/api/user/register").permitAll()
                        .antMatchers("/api/blog/public/**").permitAll()
                        .antMatchers("/swagger-ui/**", "/v3/api-docs/**","/doc.html","/sw.js","/webjars/**","/.well-known/","/favicon.ico","/swagger-resources","/v2/api-docs").permitAll() // Swagger 文档

                        // 管理员端点 - 需要 ADMIN 角色
                        .antMatchers("/api/admin/**").hasRole("ADMIN")

                        // 用户和博客端点 - 需要 USER 角色（已认证）
                        .antMatchers("/api/user/**", "/api/blog/**").hasRole("USER")

                        // 其他所有请求需要认证
                        .anyRequest().authenticated()
                )

                // 异常处理
                .exceptionHandling()
                .authenticationEntryPoint(authenticationEntryPoint) // 处理认证异常（401）
                .and()

                // 会话管理
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS) // 无状态
                .and()

                // 【修改】先添加登录过滤器，再添加JWT验证过滤器
                .addFilterBefore(jwtLoginProcessingFilter(authenticationManager(http.getSharedObject(AuthenticationConfiguration.class))),
                        UsernamePasswordAuthenticationFilter.class)
                .addFilterBefore(jwtAuthenticationFilter,
                        UsernamePasswordAuthenticationFilter.class);

        return http.build();
    }

    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOriginPatterns(Arrays.asList("*")); // 在生产环境中应指定具体域名
        configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS"));
        configuration.setAllowedHeaders(Arrays.asList("*"));
        configuration.setAllowCredentials(true);

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }


}
